# -*- coding: utf-8 -*-

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
import time
from selenium.webdriver.common.action_chains import ActionChains
import re
from pymongo import MongoClient
import requests
import json

requests.packages.urllib3.disable_warnings()  # 忽略HTTPS安全警告

"""
233网校-章节练习 获取md5并保存题
https://www.233.com/
账号：15622288121  aa1113211600020  aa1111557100016
密码：qq674401454  o49bvhp5  123456
"""

headers = {
    # 'User-Agent': ua.random,
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'keep-alive',
    'Cookie': 'gr_user_id=e339f918-df41-4ea2-b728-bb82ddae2c24; 9212495b3b2ffbcd_gr_session_id=a201eaa7-1de6-4b29-a793-fb50145585a2; UM_distinctid=17318749eeb923-026b07346b761f-4353760-144000-17318749eeca67; Hm_lvt_41458584ac7611d4bad1fc47207293a2=1593843163; 9212495b3b2ffbcd_gr_session_id_a201eaa7-1de6-4b29-a793-fb50145585a2=true; grwng_uid=22deff41-06fe-49b7-9b12-d91571e63ddd; 233ZhichiUUID=c75077ea-fb0c-4f73-9ccd-7d2464c49fff; tanchuan=1; acw_tc=2760820015938431625927105e4b389dceb2737263085ad2e2bf4751dee6b6; ASP.NET_SessionId=np0j55dcr5pb15p0p01abcwh; logRegphotoCode=97626027d29ff2021a3121fb9acd9b98; Auth=9441709A141E4791B3F01AA421257513892D57C1F0E3E27763754324C432F8BE9C6AFC9DA215CE640B6892A3FA7665C7A1CCB742A651D2FE; AuthGuid=728535750117DBDDBAB3BBD7DDFBAC2AC0392F9C409D569302C3593B57935992C33A258ED1DF8A81; UserId=29720766; wxuserinforset=username=aa1111557100016&userID=29720766&headpic=http%3A//img.233.com/wx/img/uc/Avatar.png&nickname=233%u7F51%u6821%u7F51%u53CB&isnewuser=0&addtime=2020-07-04 14:12:49&paymoney=0; clientauthentication=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIyOTcyMDc2NiIsIm5pY2tuYW1lIjoiMjMz572R5qCh572R5Y-LIiwidXNlclR5cGUiOjEsInVzZXJOYW1lIjoiYWExMTExNTU3MTAwMDE2IiwiZXhwIjoxNTkzODg2MzY5LCJ1c2VySWQiOiIyOTcyMDc2NiIsImlhdCI6MTU5Mzg0MzE2OSwianRpIjoiZThlZDAwMjMtZjViNC00ZjY2LWFjYWYtZTFhNThhOTYyMDljIn0.1ZBRLnhSknJ5ZKImkQdaLfuH6mDj0DcqOWGpsEFwiGc; 9212495b3b2ffbcd_gr_last_sent_cs1=29720766; 9212495b3b2ffbcd_gr_last_sent_sid_with_cs1=a201eaa7-1de6-4b29-a793-fb50145585a2; Hm_lpvt_41458584ac7611d4bad1fc47207293a2=1593843172; fclasscname=100; userDefaultClassId=48; i_defaultpage=48; CNZZDATA1257783334=1094124106-1593838673-https%253A%252F%252Fwww.233.com%252F%7C1593838673; CNZZDATA3583776=cnzz_eid%3D939988706-1593841766-https%253A%252F%252Fwww.233.com%252F%26ntime%3D1593841766; CNZZDATA4556415=cnzz_eid%3D475772442-1593839091-https%253A%252F%252Fwx.233.com%252F%26ntime%3D1593839091; CNZZDATA1318883=cnzz_eid%3D1210682452-1593838441-https%253A%252F%252Fwx.233.com%252F%26ntime%3D1593838441; SERVERID=84819e1e04dd99f040e4a38f9dac16db|1593843328|1593843162; 9212495b3b2ffbcd_gr_cs1=29720766',
    'DNT': '1',
    'Host': 'wx.233.com',
    'Referer': 'https://wx.233.com/tiku/chapter/do/e4c63110726d5d77d148c3dd34b0633c?isAutoDelRight=0&extractType=0&fromUrl=http%3A%2F%2Fwx.233.com%2Ftiku%2Fchapter',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest'
}


# 初始化
def init_driver(url):
    chrome_options = Options()
    # chrome_options.add_argument('--headless') # 无头模式
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) # 设置开发模式，避免被检测
    # driver = webdriver.Chrome(chrome_options=chrome_options) # 已经设置PATH环境变量
    # 未在PATH环境变量中设置，需要设置驱动可执行路径
    driver = webdriver.Chrome(executable_path='D:\\webdriver\\chromedriver.exe', chrome_options=chrome_options)
    driver.maximize_window()  # 窗口最大化
    driver.get(url)
    # html = driver.page_source
    # print(html)
    return driver

def login(drive):
    driver.find_element_by_xpath('//input[@id="account"]').send_keys("aa1111557100016")
    driver.find_element_by_xpath('//input[@id="password"]').send_keys("123456")
    driver.find_element_by_xpath('//input[@id="normalSubmit"]').click()
    return driver

# 获取页面url
def get_lx(drive, classId, tableName, title):
    # 设置等待

    # login_element = WebDriverWait(driver, 50).until(
    #         EC.presence_of_element_located((By.CLASS_NAME, "tn-tab")))
    # login_element.click()
    # driver.find_element_by_xpath('//input[@id="account"]').send_keys("aa1111557100016")
    # driver.find_element_by_xpath('//input[@id="password"]').send_keys("123456")
    # driver.find_element_by_xpath('//input[@id="normalSubmit"]').click()

    # classId = 81  # 类别id 需要修改
    selector = etree.HTML(driver.page_source)

    for s in selector.xpath('//ul[contains(@class,"problems_summary_zhang")]/li'):
        part = "".join(s.xpath('.//div[@class="pro_zhang_info"]//text()')).replace("\n", "").strip()
        for c in s.xpath('.//ol[@class="problems_summary_jie"]/li'):
            part_class = "".join(c.xpath('.//p[@class="pro_jieCont_tit"]//text()'))
            ti = c.xpath('.//p[@class="pro_jieCont_yzzt"]/i/text()')[0]
            if int(ti) > 0:
                objectid = c.xpath('.//a/@data-chapterid')[0]
                url_c = f"https://wx.233.com/tiku/exam/extractexam?classId={classId}&type=2&mode=1&objectid={objectid}&examtype=-1&count=0&redo=false&isContinue=true&isNotLogin=1&fromUrl=http://wx.233.com/tiku/chapter/{classId}&_={int(time.time() * 1000)}"
                print(f"==========={url_c}=============")
                js=f'window.open("{url_c}");'
                driver.execute_script(js)
                # 获取当前窗口句柄
                now_handle = driver.current_window_handle
                # 获取所有窗口句柄
                all_handles = driver.window_handles
                for handle in all_handles:
                    if handle != now_handle:
                        driver.switch_to.window(handle)  # 切换新打开窗口
                        try:
                            WebDriverWait(driver, 10).until(
                                EC.presence_of_element_located((By.CLASS_NAME, "txt")))
                            md5 = re.findall(r"page_paperMd5 = (.*?),", driver.page_source)[0].replace("'", "")
                            # 保存数据
                            get_part(1, md5, tableName, "章节练习", title, part, part_class)
                        except:
                            print("=========PASS=============")
                        driver.close()
            # 返回主窗口
            driver.switch_to.window(now_handle)
    drive.quit()

# 历年真题
def get_zt(drive, tableName, title):
    selector = etree.HTML(driver.page_source)
    for s in selector.xpath('//div[@class="pracl-dalist"]//li'):
        if len(s.xpath('./span[@class="dal-but"]')) > 0:
            part_class = s.xpath("./div/h3/a/text()")[0].replace("\n", "").strip()
            url_c = "https://wx.233.com" + s.xpath("./div/h3/a/@href")[0]
            js=f'window.open("{url_c}");'
            driver.execute_script(js)
            # 获取当前窗口句柄
            now_handle = driver.current_window_handle
            # 获取所有窗口句柄
            all_handles = driver.window_handles
            for handle in all_handles:
                if handle != now_handle:
                    driver.switch_to.window(handle)  # 切换新打开窗口
                    try:
                        # 点击 练习模式
                        WebDriverWait(driver, 10).until(
                            EC.presence_of_element_located((By.XPATH, '//p[@class="bd"]//a[contains(text(),"练习模式") or contains(text(),"继续练习")]'))).click()
                        WebDriverWait(driver, 10).until(
                            EC.presence_of_element_located((By.CLASS_NAME, "txt")))
                        md5 = re.findall(r"page_paperMd5 = (.*?),", driver.page_source)[0].replace("'", "")
                        # 保存数据
                        get_part(1, md5, tableName, "历年真题", title, part_class, "")
                    except:
                        print("=========PASS=============")
                    driver.close()
            # 返回主窗口
            driver.switch_to.window(now_handle)
    print("=========历年真题【结束】=============")
    drive.quit()

# 模拟试题
def get_mn(drive, tableName, title):
    selector = etree.HTML(driver.page_source)
    for s in selector.xpath('//div[@class="pracl-dalist"]//li'):
        if len(s.xpath('./span[@class="dal-but"]')) > 0:
            part_class = s.xpath("./div/h3/a/text()")[0].replace("\n", "").strip()
            url_c = "https://wx.233.com" + s.xpath("./div/h3/a/@href")[0]
            js=f'window.open("{url_c}");'
            driver.execute_script(js)
            # 获取当前窗口句柄
            now_handle = driver.current_window_handle
            # 获取所有窗口句柄
            all_handles = driver.window_handles
            for handle in all_handles:
                if handle != now_handle:
                    driver.switch_to.window(handle)  # 切换新打开窗口
                    try:
                        # 点击 练习模式
                        WebDriverWait(driver, 10).until(
                            EC.presence_of_element_located((By.XPATH, '//p[@class="bd"]//a[contains(text(),"练习模式") or contains(text(),"继续练习")]'))).click()
                        WebDriverWait(driver, 10).until(
                            EC.presence_of_element_located((By.CLASS_NAME, "txt")))
                        md5 = re.findall(r"page_paperMd5 = (.*?),", driver.page_source)[0].replace("'", "")
                        # 保存数据
                        get_part(1, md5, tableName, "模拟试题", title, part_class, "")
                    except:
                        print("=========PASS=============")
                    driver.close()
            # 返回主窗口
            driver.switch_to.window(now_handle)
    print("=========模拟试题【结束】=============")
    drive.quit()


def get_part(cursor, md5, tablename, type, title, part, part_class):
    postData = {
        'md5': md5,
        'type': '2',
        'pageIndex': cursor,
        'pageSize': '20',
        'isError': '0',
        '_': int(time.time() * 1000)

    }
    url = f"https://wx.233.com/tiku/exam/GetExam"
    html = get_request("GET", url, headers, postData)
    data_json = json.loads(html.text)
    count = data_json['list']['count']  # 总题数
    page = len(data_json['list']['listPageMap'])  # 总页数
    for d in data_json['list']['examDtoList']:
        dict_data = dict()
        dict_data['type'] = type  # 类别
        dict_data['title'] = title  # 科目
        dict_data['part'] = part  # 章
        dict_data['part_class'] = part_class  # 节
        dict_data['examId'] = d['examId']  # id
        dict_data['examTypeName'] = d['examTypeName']  # 题型
        dict_data['content'] = d['content']  # 题干
        dict_data['returnQuestion'] = d['questionArr']['returnQuestion']  # 问题
        dict_data['analysis'] = d['analysis']  # 分析
        dict_data['answer'] = d['answer']  # 正确答案选项
        if d['examTypeName'] == "判断题":
            if d['answer'] == "0":
                dict_data['answer'] = "错误"
            elif d['answer'] == "1":
                dict_data['answer'] = "正确"
            else:
                dict_data['answer'] = ""

        # 选项
        tag_count = 1
        for t in d['optionList']:
            dict_data['option_' + str(tag_count)] = t.replace("&nbsp;", "")
            tag_count += 1
        # 章+节
        if len(d['knowledge']) > 0:
            parentChapterName = d['knowledge'][0]['parentChapterName']  # 章
            chapterName = d['knowledge'][0]['chapterName']  # 节
            knowLedgeName = d['knowledge'][0]['knowLedgeName']  # 节
            yaoQiuName = d['knowledge'][0]['yaoQiuName']  # 节
            pageNum = d['knowledge'][0]['pageNum']  # 教材页码
            dict_data['zsd'] = parentChapterName + ">" + chapterName + ">" + knowLedgeName + ">" + "(" + yaoQiuName + ")"
            dict_data['ym'] = pageNum
        insertItem(tablename, dict_data)
        print(str(dict_data))
        # 如果有不定项选择题
        if d['examTypeName'] == "不定项选择题":
            for c in d['subQuestion']:
                dict_data_c = dict()
                dict_data_c['type'] = type  # 类别
                dict_data_c['title'] = title  # 科目
                dict_data_c['part'] = part  # 章
                dict_data_c['part_class'] = part_class  # 节
                dict_data_c['examId'] = d['examId']  # 上级id
                dict_data_c['examId_c'] = c['examId']  # id
                dict_data_c['examTypeName'] = c['examTypeName']  # 题型
                dict_data_c['content'] = d['content']  # 题干
                dict_data_c['subexamId'] = c['examId']  # id
                dict_data_c['examTypeName'] = c['examTypeName']  # 题型
                dict_data_c['returnQuestion'] = c['questionArr']['returnQuestion']  # 问题
                dict_data_c['analysis'] = c['analysis']  # 分析
                dict_data_c['answer'] = c['answer']  # 正确答案选项
                # 选项
                tag_count = 1
                for t in c['optionList']:
                    dict_data_c['option_' + str(tag_count)] = t.replace("&nbsp;", "")
                    tag_count += 1
                # 章+节
                if len(c['knowledge']) > 0:
                    parentChapterName = c['knowledge'][0]['parentChapterName']  # 章
                    chapterName = c['knowledge'][0]['chapterName']  # 节
                    knowLedgeName = c['knowledge'][0]['knowLedgeName']  # 节
                    yaoQiuName = c['knowledge'][0]['yaoQiuName']  # 节
                    pageNum = c['knowledge'][0]['pageNum']  # 教材页码
                    dict_data_c['zsd'] = parentChapterName + ">" + chapterName + ">" + knowLedgeName + ">" + yaoQiuName
                    dict_data_c['ym'] = pageNum
                insertItem(tablename, dict_data_c)
                print(str(dict_data_c))

    # 翻页
    if cursor < page:
        print(f"============共【{page}】页，第【{cursor + 1}】页=============")
        get_part(cursor + 1, md5, tablename, type, title, part, part_class)



    # 封装请求方法
def get_request(method, url, headers, data, retry=1):
    # cookies = self.get_cookie_dict("JSESSIONID=D79B2E69AADDABD4A2A0B5352C4A1987")
    res = None
    try:
        if method == "POST":
            if headers == "":
                if url.find("https") == 0:
                    res = requests.post(url, data=data, verify=False)
                else:
                    res = requests.post(url, data=data)
            else:
                if url.find("https") == 0:
                    res = requests.post(url, headers=headers, data=data, verify=False)
                else:
                    res = requests.post(url, headers=headers, data=data)
        elif method == "GET":
            if headers == "":
                if url.find("https") == 0:
                    res = requests.get(url, params=data, verify=False)
                else:
                    res = requests.get(url, params=data)
            else:
                if url.find("https") == 0:
                    res = requests.get(url, headers=headers, params=data, verify=False)
                else:
                    res = requests.get(url, headers=headers, params=data)
        else:
            res = None
    except Exception as ex:
        print(f"-------------【错误】,重试第【{retry}】次-------------")
        print(ex)
        max_retry = 3  # 重试次数
        if retry <= max_retry:
            retry += 1
            return get_request(method, url, headers, data, retry)
    else:
        if res.status_code != 200:
            max_retry = 3  # 重试次数
            if retry <= max_retry:
                print(f"-------------返回状态码:{res.status_code},重试第【{retry}】次-------------")
                retry += 1
                return get_request(method, url, headers, data, retry)
    return res

def insertItem(tableName, data):
    my_set = db[tableName]
    my_set.insert_one(data)


if __name__ == '__main__':
    conn = MongoClient('127.0.0.1', 27017)
    db = conn["Test"]
    url = "https://passport.233.com/login/?redirecturl=https%3A//www.233.com/"

    driver = init_driver(url)

    driver = login(driver)

    classId = 584  # 类别id 需要修改
    tableName = "233网校_注册会计师"
    title = "注册会计师 - 公司战略与风险管理"

    # 章节练习
    # get_lx(driver, classId, tableName, title)

    # 历年真题
    # get_zt(driver, tableName, title)

    # 模拟试题
    get_mn(driver, tableName, title)
